/*
 * Created by SharpDevelop.
 * User: MyWife
 * Date: 10/11/2009
 * Time: 8:43 PM
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */

using System;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using popLib;
using System.Threading;
using System.Data;
using System.Diagnostics;
using System.Windows.Forms;
using System.Text;

namespace FileTransferSocket
{
	/// <summary>
	/// Description of Server.
	/// </summary>
	public class Server{
		
		public delegate void ConnectEvent(string ip);
		public event ConnectEvent ClientConnected;

        Hashtable clients;
		
		
		public Server(int port)
		{
			try{
                clients = new Hashtable();

				Thread current 		 = new Thread( new System.Threading.ParameterizedThreadStart(starter) );
				current.IsBackground = true;
				current.Start( port );
			}catch(Exception ex){
				FileLib.writeLog( FileLib.getFullPath("FileLog.txt"), ex, "ClientHandler" );
			}
		}
		
		public void starter(object obj){
			try{
				TcpListener tcpListener = new TcpListener( IPAddress.Any , (int)obj);
				tcpListener.Start();
				while(true){
	    			Socket socket = tcpListener.AcceptSocket();
	    			if(socket.Connected){
	    				if(ClientConnected!=null) ClientConnected(socket.RemoteEndPoint.ToString().Split(':')[0]);

                        HandleClient client = new HandleClient(socket);
                        if (!clients.ContainsKey(client.IPAddress))
                            clients.Add(client.IPAddress, client);
	    			}
				}
			}catch(Exception ex){
				if( ex.ToString().IndexOf("System.Net.Sockets.SocketException: Only one usage of each socket address") == -1 )
					FileLib.writeLog( FileLib.getFullPath("FileLog.txt"), ex, "ClientHandler" );
				else FormLib.alert("Only one usage of each socket address");
				
			}
		}

        public void SendFile(string file, string ipaddress, int currentFileIndex, int totalFiles) {
            if (clients.ContainsKey(ipaddress))
            {
                ((HandleClient)clients[ipaddress]).SendFile(file, currentFileIndex, totalFiles);
            }
        }
		
		public void Shutdown(){
			foreach( HandleClient client in clients.Values )
				client.CientSocket.Shutdown(SocketShutdown.Both);
        }
	}

    class HandleClient {
        Socket socket;
        NetworkStream networkStream;

        public HandleClient(Socket socket)
        {
            this.socket = socket;
            this.socket.ReceiveBufferSize = Global.Singleton().SocketBufferSize;
            this.socket.SendBufferSize = Global.Singleton().SocketBufferSize;
            networkStream = new NetworkStream(socket);

            Thread current = new Thread(HandleSocket);
            current.IsBackground = true;
            current.Start();
        }

        public void HandleSocket()
        {
            while (true) Global.Singleton().handleStream(socket, networkStream);
        }

        public void SendFile(string file, int currentFileIndex, int totalFiles)
        {
            Global.Singleton().sendFile(file, currentFileIndex, totalFiles,  socket);
        }

        public string IPAddress
        {
            get
            {
                return socket.RemoteEndPoint.ToString().Split(':')[0];
            }
        }
        
        public Socket CientSocket
        {
            get
            {
                return socket;
            }
        }

    }
}
